<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    
    <title>Node.js 入门 | liuz2&#39;s Blog</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1">
    <meta name="generator" content="Hugo 0.63.1" />
    
    
      <META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
    

    
    
      <link href="/dist/css/app.9576afd3b3c158d98f48ec5df01fec6a.css" rel="stylesheet">
    

    

    
      

    

    

    <meta property="og:title" content="Node.js 入门" />
<meta property="og:description" content="Node.js 零基础入门" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://liuz2.gitee.io/posts/node-intro/" />
<meta property="article:published_time" content="2021-09-04T15:47:00+08:00" />
<meta property="article:modified_time" content="2021-09-04T15:47:00+08:00" />
<meta itemprop="name" content="Node.js 入门">
<meta itemprop="description" content="Node.js 零基础入门">
<meta itemprop="datePublished" content="2021-09-04T15:47:00&#43;08:00" />
<meta itemprop="dateModified" content="2021-09-04T15:47:00&#43;08:00" />
<meta itemprop="wordCount" content="411">



<meta itemprop="keywords" content="node," /><meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Node.js 入门"/>
<meta name="twitter:description" content="Node.js 零基础入门"/>

	
  </head>

  <body class="ma0 avenir bg-white">

    
   
  

  <header>
    <div class="bg-black">
      <nav class="pv3 ph3 ph4-ns" role="navigation">
  <div class="flex-l justify-between items-center center">
    <a href="/" class="f3 fw2 hover-white no-underline white-90 dib">
      
        liuz2&#39;s Blog
      
    </a>
    <div class="flex-l items-center">
      

      
        <ul class="pl0 mr3">
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/about/" title="About page">
              About
            </a>
          </li>
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/links/" title="Links page">
              Links
            </a>
          </li>
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/timeline/" title="Timeline page">
              Timeline
            </a>
          </li>
          
        </ul>
      
      















    </div>
  </div>
</nav>

    </div>
  </header>



    <main class="pb7" role="main">
      
  
  <article class="flex-l flex-wrap justify-between mw8 center ph3">
    <header class="mt4 w-100">
      <h1 class="f3 athelas mt3 mb1">Node.js 入门</h1>
      
      
      <time class="f6 mv1 dib tracked" datetime="2021-09-04T15:47:00&#43;08:00">September 4, 2021</time>

      
      
    </header>
    <div class="nested-copy-line-height lh-copy sans-serif f5 nested-links nested-img mid-gray pr4-l w-two-thirds-l"><p>Node.js 是一款基于 Chrome V8 引擎的 JavaScript 运行时。</p>
<p>Node.js 每年大版本更新两次，上半年偶数版本（10、12 等），下半年奇数版本（11、13 等）。官方对于奇偶版本的技术支持时间不同。偶数版本有 3 年的技术支持，而奇数版本只有半年。因此，<strong>生产环境务必使用偶数版本的 Node.js</strong>。</p>
<p>目前最新的稳定版是 v14.17.6 LTS，官方建议大部分用户使用。通常用 <a href="https://github.com/nvm-sh/nvm" title="Node Version Manager">nvm</a> 管理本机多版本 Node.js。</p>
<h2 id="hello-world">Hello World</h2>
<p>以下是 Node.js 版 <code>Hello World</code> 代码：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">http</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;http&#39;</span>);

<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">hostname</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;127.0.0.1&#39;</span>;
<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">port</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">3000</span>;

<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">server</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">createServer</span>((<span style="color:#a6e22e">req</span>, <span style="color:#a6e22e">res</span>) =&gt; {
    <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">statusCode</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">200</span>;
    <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">setHeader</span>(<span style="color:#e6db74">&#39;Content-Type&#39;</span>, <span style="color:#e6db74">&#39;text/plain&#39;</span>);
    <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">end</span>(<span style="color:#e6db74">&#39;Hello World&#39;</span>);
});

<span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">listen</span>(<span style="color:#a6e22e">port</span>, <span style="color:#a6e22e">hostname</span>, () =&gt; {
    <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">`</span><span style="color:#e6db74">Server running at http://</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">hostname</span><span style="color:#e6db74">}</span><span style="color:#e6db74">:</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">port</span><span style="color:#e6db74">}</span><span style="color:#e6db74">/</span><span style="color:#e6db74">`</span>);
});
</code></pre></div><p><code>req</code> 变量是 <code>http.IncomingMessage</code> 类型，包含请求信息。如果要查看请求方法或路由，可以使用：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">method</span>, <span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">url</span>);
</code></pre></div><p>此时，如果使用 <code>curl '127.0.0.1:3000/hello/world?foo=bar&amp;hello=world'</code> 请求服务器，会在服务器终端看到输出：</p>
<pre><code>GET /hello/world?foo=bar&amp;hello=world
</code></pre><p><code>res</code> 是 <code>http.ServerResponse</code> 类型，它可以设定响应状态码 <code>statusCode</code>，响应头 <code>setHeader(name, value)</code> 和响应体 <code>end(body)</code> 等信息。</p>
<h2 id="node-简史">Node 简史</h2>
<table>
<thead>
<tr>
<th>年份</th>
<th>大事件</th>
</tr>
</thead>
<tbody>
<tr>
<td>1995</td>
<td>JavaScript 诞生</td>
</tr>
<tr>
<td>2008</td>
<td>Chrome 浏览器和 V8 引擎上市</td>
</tr>
<tr>
<td>2009</td>
<td>Node.js 诞生；npm 初版诞生</td>
</tr>
<tr>
<td>2010</td>
<td><a href="https://expressjs.com/">Express</a> 诞生；Socket.io 诞生</td>
</tr>
<tr>
<td>2011</td>
<td>npm v1.0；LinkedIn, Uber 等大公司开始采用 Node.js；hapi 诞生</td>
</tr>
<tr>
<td>2012</td>
<td>快速流行</td>
</tr>
<tr>
<td>2013</td>
<td>第一个大型博客平台 <a href="https://ghost.org/">Ghost</a> 使用 Node.js；<a href="https://koajs.com/">Koa</a> 诞生</td>
</tr>
<tr>
<td>2014</td>
<td>重大分叉：IO.js 期望引入 ES6，发展迅猛</td>
</tr>
<tr>
<td>2015</td>
<td>Node.js 基金会成立；IO.js 回归 Node.js；npm 引入私有模块；Node.js 4（v1, v2, v3 从未发布）</td>
</tr>
<tr>
<td>2016</td>
<td><a href="https://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm">leftpad</a> 事件；<a href="https://classic.yarnpkg.com/en/">Yarn</a> 诞生；Node.js 6；</td>
</tr>
<tr>
<td>2017</td>
<td>npm 关注安全问题；Node.js 8；HTTP/2；V8 将 Node.js 引入测试用例；npm 周下载量达到 30 亿次</td>
</tr>
<tr>
<td>2018</td>
<td>Node.js 10；尝试支持 <a href="https://nodejs.org/api/esm.html">ES</a> 模块 <code>.mjs</code>；</td>
</tr>
<tr>
<td>2019</td>
<td>Node.js 12；</td>
</tr>
<tr>
<td>2020</td>
<td>Node.js 14；</td>
</tr>
<tr>
<td>2021</td>
<td>Node.js 16；</td>
</tr>
</tbody>
</table>
<h2 id="v8-引擎">V8 引擎</h2>
<p><a href="https://v8.dev/" title="V8 JavaScript Engine">V8 引擎</a>用于驱动 Google Chrome 浏览器，使用 C++ 编写。</p>
<p>从 2021 Q3 开始，V8 和 Chrome 每月一次<a href="https://v8.dev/blog/faster-releases" title="Faster releases">大版本更新</a>。</p>
<p>V8 仅提供 JavaScript 的运行环境，DOM 和其他 Web 平台 API 由浏览器提供。</p>
<p>其他的 JS 引擎还有 Firefox 的 <a href="https://spidermonkey.dev/" title="SpiderMonkey JavaScript/WebAssembly Engine, written in C++, Rust and JavaScript">SpiderMonkey</a> 和 Safari 的 <a href="https://developer.apple.com/documentation/javascriptcore">JavaScriptCore</a>。不同引擎在性能上竞赛，开发者受益匪浅。</p>
<p>通常认为 JavaScript 是一门解释性语言，但是现代 JS 引擎早已超越单纯的解释器，它们会将 JS 编译为机器代码运行。2009 年，Firefox 3.5 引入 SpiderMonkey JavaScript 编译器，此后其他引擎纷纷效仿。</p>
<h2 id="退出应用">退出应用</h2>
<p>在终端可以使用 <code>ctrl-C</code> 退出 Node.js 应用。</p>
<h3 id="粗暴退出">粗暴退出</h3>
<p>在代码里，最粗暴的退出是 <code>process.exit()</code>。一旦执行，应用立即结束，根本不会考虑等待中的回调函数、发送中的网络请求、文件系统读写等等操作。如果这就是你要的，用 <code>process.exit()</code> 吧。还可以向操作系统传递一个退出码。</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">exit</span>(<span style="color:#ae81ff">1</span>);
</code></pre></div><p>默认的退出码是 <code>0</code>，表示成功退出。非零退出码有<a href="https://nodejs.org/api/process.html#process_exit_codes" title="Exit codes">不同的含义</a>。</p>
<blockquote>
<p>如果想在 shell 中打印最新的退出码，可以使用 <code>echo $?</code>。</p>
</blockquote>
<p>还可以设定 <code>process.exitCode</code> 属性，当程序退出时，Node.js 返回设定的退出码：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">exitCode</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</code></pre></div><p>如果我们架设了自己的服务器：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">express</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;express&#39;</span>);
<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">app</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">express</span>();

<span style="color:#a6e22e">app</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;/&#39;</span>, (<span style="color:#a6e22e">req</span>, <span style="color:#a6e22e">res</span>) =&gt; {
    <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">send</span>(<span style="color:#e6db74">&#39;Hi!&#39;</span>);
});

<span style="color:#a6e22e">app</span>.<span style="color:#a6e22e">listen</span>(<span style="color:#ae81ff">3000</span>, () =&gt; <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#39;Server ready&#39;</span>));
</code></pre></div><p>执行 <code>process.exit()</code> 将直接切断正在进行的用户请求，这种做法不好。</p>
<h3 id="优雅退出">优雅退出</h3>
<p>更好的做法是发送 <code>SIGTERM</code> 信号，并在信号处理函数中妥善处理，最后优雅退出：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#75715e">// ... same code as above ...
</span><span style="color:#75715e"></span>
<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">server</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">app</span>.<span style="color:#a6e22e">listen</span>(<span style="color:#75715e">/* ... */</span>);

<span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">on</span>(<span style="color:#e6db74">&#39;SIGTERM&#39;</span>, () =&gt; {
    <span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">close</span>(() =&gt; {
        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#39;Process terminated&#39;</span>);
    });
});
</code></pre></div><blockquote>
<p>信号是什么？信号是 POSIX 进程间的通信机制：用于通知某个进程，告诉它发生了什么事儿。</p>
</blockquote>
<p><code>SIGKILL</code> 信号通知进程立即结束，效果和执行 <code>process.exit()</code> 类似。</p>
<p>如何发送信号呢？如果是同一个进程，可以使用：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">kill</span>(<span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">pid</span>, <span style="color:#e6db74">&#39;SIGTERM&#39;</span>);
</code></pre></div><p>如果知道进程的 pid，可以在 shell 中使用 <code>kill</code> 命令发送 <code>SIGTERM</code> 信号：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ kill -SIGTERM &lt;pid&gt;
</code></pre></div><blockquote>
<p>如果要查看 Node.js 的应用，可以使用 <code>ps | grep node</code> 过滤查看。</p>
</blockquote>
<h2 id="读取环境变量">读取环境变量</h2>
<p><code>process.env</code> 存储着启动应用的所有变量。如果通过以下命令启动 Node.js 应用：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ USER_ID<span style="color:#f92672">=</span><span style="color:#ae81ff">9527</span> USER_KEY<span style="color:#f92672">=</span>foobar node app.js
</code></pre></div><p>如果环境变量较多，可以在根目录创建 <code>.env</code> 文件，并且使用 <a href="https://www.npmjs.com/package/dotenv" title="dotenv - npm">dotenv</a> 加载：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#75715e"># .env file</span>
USER_ID<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;9527&#34;</span>
USER_KEY<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;foobar&#34;</span>
NODE_ENV<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;development&#34;</span>
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#75715e">// your js file
</span><span style="color:#75715e"></span><span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;dotenv&#39;</span>).<span style="color:#a6e22e">config</span>();

<span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">USER_ID</span>; <span style="color:#75715e">// 9527
</span><span style="color:#75715e"></span><span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">USER_KEY</span>; <span style="color:#75715e">// foobar
</span><span style="color:#75715e"></span><span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">NODE_ENV</span>; <span style="color:#75715e">// development
</span></code></pre></div><blockquote>
<p>如果不想在代码中引入 <code>dotenv</code> 包，还可以使用 <code>node -r dotenv/config index.js</code> 命令。</p>
</blockquote>
<blockquote>
<p><a href="https://nodejs.org/dist/latest-v14.x/docs/api/cli.html#cli_r_require_module"><code>-r, --require &lt;module&gt;</code></a> 表示在 Node.js 启动时预加载 <code>&lt;module&gt;</code> 模块。</p>
</blockquote>
<h2 id="命令行参数">命令行参数</h2>
<p>使用 <a href="https://nodejs.dev/learn/nodejs-accept-arguments-from-the-command-line"><code>process.argv</code></a> 可以读取命令行参数。它是一个数组类型，第一个元素是 Node 的可执行文件的绝对路径，第二个参数是入口文件的绝对路径，后面依次是空格分离的参数元素。</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#75715e">// app.js
</span><span style="color:#75715e"></span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">argv</span>);
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(Array.<span style="color:#a6e22e">isArray</span>(<span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">argv</span>));
</code></pre></div><p>如果执行命令 <code>node app.js foo=bar -- hello</code>，会得到如下输出：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>
  <span style="color:#e6db74">&#39;/path/to/node&#39;</span>,
  <span style="color:#e6db74">&#39;/path/to/app.js&#39;</span>,
  <span style="color:#e6db74">&#39;foo=bar&#39;</span>,
  <span style="color:#e6db74">&#39;--&#39;</span>,
  <span style="color:#e6db74">&#39;hello&#39;</span>
<span style="color:#f92672">]</span>
true
</code></pre></div><h2 id="ref">REF</h2>
<ol>
<li><a href="https://nodejs.org/en/">Node.js 官网</a></li>
<li><a href="https://nodejs.org/en/about/releases/">Releases | Node.js</a></li>
<li><a href="https://nodejs.dev/learn">Introduction to Node.js</a></li>
<li><a href="https://nodejs.dev/learn/a-brief-history-of-nodejs">A brief history of Node.js</a></li>
</ol>
<a href="https://gitee.com/liuz2/liuz2/blob/master/content/posts/node-intro.md#tree_comm_title" class="no-underline db b--black pa2 tc bg-black-90" style="color:#eee;">进入留言</a><ul class="pa0">
  
   <li class="list dib">
     <a href="/tags/node" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">node</a>
   </li>
  
</ul>
<div class="mt6 instapaper_ignoref">
      
      
      </div>
    </div>

    <aside class="w-30-l mt6-l"><div class="bg-light-gray pa3 nested-list-reset nested-copy-line-height nested-links">
    <p class="f5 b mb3">目录</p>
      <nav id="TableOfContents">
  <ul>
    <li><a href="#hello-world">Hello World</a></li>
    <li><a href="#node-简史">Node 简史</a></li>
    <li><a href="#v8-引擎">V8 引擎</a></li>
    <li><a href="#退出应用">退出应用</a>
      <ul>
        <li><a href="#粗暴退出">粗暴退出</a></li>
        <li><a href="#优雅退出">优雅退出</a></li>
      </ul>
    </li>
    <li><a href="#读取环境变量">读取环境变量</a></li>
    <li><a href="#命令行参数">命令行参数</a></li>
    <li><a href="#ref">REF</a></li>
  </ul>
</nav>
  </div>




  <div class="bg-light-gray pa3 nested-list-reset nested-copy-line-height nested-links">
    <p class="f5 b mb3">相关內容</p>
    <ul class="pa0 list">
	   
	     <li  class="mb2">
          <a href="/posts/debug-nodejs/">调试 Node.js</a>
        </li>
	    
    </ul>
</div>

</aside>

  </article>

    </main>
    <footer class="bg-black bottom-0 w-100 pa3" role="contentinfo">
  <div class="flex justify-between">
  <a class="f4 fw4 hover-white no-underline white-70 dn dib-ns pv2 ph3" href="https://liuz2.gitee.io/" >
    &copy;  liuz2's Blog 2022 
  </a>
    <div>














</div>
  </div>
</footer>

    

  <script src="/dist/js/app.3fc0f988d21662902933.js"></script>


  </body>
</html>
